import * as THREE from 'three'
import createApp from '../../core'
import { ParametricGeometry } from 'three/examples/jsm/geometries/ParametricGeometry'

function createParametricGeometry (dom: HTMLElement) {
  const { camera, scene, update, gui } = createApp(dom)
  camera.position.set(0, 0, 100)
  camera.lookAt(scene.position)

  const mesh = createParametricFromGeometry()
  mesh.position.set(0, 0, 0)
  scene.add(mesh)

  update((time: number) => {
    const angle = time / 2000
    mesh.rotation.set(angle, angle, 0)
  })

  function updateMeshs () {
    generateGeometry(mesh)
  }

  gui.add(data, 'slices', 0, 60, 1).onChange(updateMeshs)
  gui.add(data, 'stacks', 0, 60, 1).onChange(updateMeshs)
}

const data = {
  slices: 25,
  stacks: 25
}

function paramFunc (u: number, v: number, target: THREE.Vector3) {
  // 参数化平面的宽度
  const width = 30
  // 参数化平面的长度
  const height = 60
  const x = Math.sin(u) * width
  const z = Math.sin(v / 2) * 2 * height
  const y = (Math.sin(u * 4 * Math.PI) + Math.cos(v * 2 * Math.PI)) * 2.8
  target.set(x, y, z)
}

function createParametricFromGeometry () {
  const { slices, stacks } = data
  const geometry = new ParametricGeometry(paramFunc, slices, stacks)
  const material = new THREE.MeshNormalMaterial({ side: THREE.DoubleSide, wireframe: true })
  const meth = new THREE.Mesh(geometry, material)
  return meth
}

function generateGeometry (mesh: THREE.Mesh) {
  const { slices, stacks } = data
  const geometry = new ParametricGeometry(paramFunc, slices, stacks)
  mesh.geometry.dispose()
  mesh.geometry = geometry
}

export {
  createParametricGeometry
}
